#include <stdio.h>
#include <stdlib.h>

#include <pile.h>

Pile* pBase = NULL;
Pile* pTete = NULL;

Pile* getBase() {
	return pBase;
}

void initBase(){
	pBase = NULL;
}

Pile* getTete() {
	return pTete;
}

void push(int type, void *data) {
	if(pBase == NULL){
		pBase = pTete = malloc(sizeof(Pile));
		pBase->suiv = NULL; pBase->prec = NULL;
	}else{
		pTete->suiv = malloc(sizeof(Pile));
		pTete->suiv->prec = pTete;
		pTete = pTete->suiv;
		pTete->suiv = NULL;
	}

	pTete->type = type;

	switch(type){
		case INT:{
			int* ptr = malloc(sizeof(int));
			int* ptr2 = (int*) data;
			*ptr = *ptr2;
			pTete->ptr_val = (void *) ptr;
			break;
		}
		case DOUBLE:{
			double* ptr = malloc(sizeof(double));
			double* ptr2 = (double*) data;
			*ptr = *ptr2;
			pTete->ptr_val = (void *) ptr;
			break;
		}
		case BOOLEAN: {
			bool* ptr = malloc(sizeof(bool));
			bool* ptr2 = (bool*) data;
			*ptr = *ptr2;
			pTete->ptr_val = (void *) ptr;
			break;
		}
		case CHARACTER: {
			char* ptr = malloc(sizeof(char));
			char* ptr2 = (char*) data;
			*ptr = *ptr2;	
			pTete->ptr_val = (void *) ptr;
			break;
		}
		case STRING: {
			char* ptr = malloc( (sizeof(char) * strlen(data) ) + 1);
			strcpy(ptr, data); 
			
			pTete->ptr_val = (void *) ptr;
			
			break;
		}
	}
	
}

void* pop(int* type) {
	void* ptr = pTete->ptr_val;
	*type = pTete->type;
	
	if(pTete->prec != NULL){
		pTete = pTete->prec;
		free(pTete->suiv);
      pTete->suiv = NULL;
	}else{
		free(pTete);
		pTete = pBase = NULL;
	}
	
	return ptr;
}

void supprimer_pile() {
   Pile* ptr = pBase;
   Pile* tmp;

   while (ptr != NULL) {
      tmp = ptr->suiv;
      free(ptr);
      ptr = tmp;
   }

}

void afficher_pile() {
	
	Pile* ptr = pBase; int i=0;
	while(ptr!=NULL){
		printf("Rang : %d; Type : %d; Valeur : ", i, ptr->type);
		switch(ptr->type) {
			case INT: {
				int* iP = (int*)ptr->ptr_val;
				printf("%d", *iP);
				break;
            }
			case DOUBLE: {
				double* dP = (double*)ptr->ptr_val;
				printf("%f", *dP);
				break;
            }
            case BOOLEAN: {
				bool* dP = (bool*)ptr->ptr_val;
				printf("%d", *dP);
				break;
			}
			case CHARACTER: {
				char* dP = (char*)ptr->ptr_val;
				printf("%c", *dP);
				break;
			}
			case STRING: {
				char *str = malloc( ( sizeof(char) * strlen(ptr->ptr_val) ) + 1);
				strcpy(str, ptr->ptr_val);
				
				printf("%s", str);
				break;
			}
				default:
					printf("%p", ptr->ptr_val);
			}
		ptr = ptr->suiv; ++i;
      printf("\n");
	}

}

void maj_pile(int index, void * valeur) {
	
	Pile* ptr = pBase;
	
	for(; index > 0; --index) {
		ptr = ptr->suiv;
	}
	
	switch(ptr->type){
		case INT:{
			int* val = (int*) valeur;
			int i = *val;
			val = pTete->ptr_val;
			*val = i;
			break;
		}
		case DOUBLE:{
			double* val = (double *) valeur;
			double i = *val;
			val = pTete->ptr_val;
			*val = i;
			break;
		}
	}

}

int getType(int index) {
	Pile* ptr = pBase;
	
	for(; index > 0; --index) {
		ptr = ptr->suiv;
	}
	
	return ptr->type;
}



